/*
Brick And Blast, a crossplatform breakout game.
 Copyright (C) 2008-2010 Julien CLEMENT (andematunum@gmail.com)
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 

*/

#include "ObjectGrid.h"
#include "GameObject.h"

#include <iostream>
using namespace std;

/**
* file   ObjectGrid.cpp
* date   Mar 29 déc 2009 14:04:17 CET
* brief  TODO
 */

void
ObjectGrid::
add_object (GameObject* object) {
  const SDL_Rect* rect = object->get_rect();
  set< Cell* > cells;
  get_intersected_cells(cells, *rect);
  set< Cell* >& obj_cells = object->get_grid_cells();

  if ( !obj_cells.empty() ) {
    cout << "*** WARNING: Object cell list is not empty." << endl;
    obj_cells.clear();
  }

  for (set< Cell* >::iterator itr = cells.begin();
       itr != cells.end(); itr++) {
    Cell* cell = *itr;
    obj_cells.insert(cell);
    cell->insert(object);
  }
}

void
ObjectGrid::
remove_object (GameObject* object) {
  set < Cell* >& obj_cells = object->get_grid_cells();
  for (set< Cell* >::iterator itr = obj_cells.begin();
      itr != obj_cells.end(); itr++) {
    Cell* cell = *itr;
    cell->erase(object);
  }
  obj_cells.clear();
}

void
ObjectGrid::
get_neighborhood (set<GameObject*>& neighbors, set< Cell* >& cells,
                  GameObject* object) {
  const SDL_Rect* rect = object->get_next_rect();
  get_intersected_cells(cells, *rect);
 
  for (set< Cell* >::iterator itr = cells.begin();
      itr != cells.end(); itr++) {
    Cell* cell = *itr;

    for (set<GameObject*>::iterator cellitr = cell->begin();
         cellitr != cell->end(); cellitr++) {
      GameObject* neigh = *cellitr;
      if (neigh == object) {
        continue;
      }
      neighbors.insert(neigh);
    }
  } 
}

void
ObjectGrid::
update_object (GameObject* object, set< Cell* >& cells) {
  set< Cell* >& current_cells = object->get_grid_cells();
  remove_object(object);
  for (set< Cell* >::iterator itr = cells.begin();
       itr != cells.end(); itr++) {
    Cell* cell = *itr;
    current_cells.insert(cell);
    cell->insert(object);
  }
}

void
ObjectGrid::
get_intersected_cells (set< Cell* >& cells, const SDL_Rect& rect) {
  SDL_Point a = { rect.x, rect.y };
  SDL_Point b = { rect.x+rect.w, rect.y };
  SDL_Point c = { rect.x+rect.w, rect.y+rect.h };
  SDL_Point d = { rect.x, rect.y+rect.h };

  SDL_Point ga;
  SDL_Point gb;
  SDL_Point gc;
  SDL_Point gd;

  pixel_2_grid(ga,a);
  pixel_2_grid(gb,b);
  pixel_2_grid(gc,c);
  pixel_2_grid(gd,d);

  cells.insert(get_cell(ga));
  cells.insert(get_cell(gb));
  cells.insert(get_cell(gc));
  cells.insert(get_cell(gd));
}

